/**
 * @version 2007-5-10
 * @author xalinx at gmail dot com
 */
package org.nanhill.support.spring.dbutil;

import java.util.List;

import org.nanhill.commons.dbutil.builder.BeanMonitor;
import org.nanhill.commons.dbutil.builder.QueryWrap;
import org.nanhill.commons.dbutil.builder.SqlBuilder;
import org.nanhill.commons.dbutil.pagequery.BasePage;
import org.nanhill.commons.dbutil.pagequery.PageQuery;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcOperations;
import org.springframework.jdbc.core.simple.ParameterizedRowMapper;
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
import org.springframework.util.ObjectUtils;

/**
 * @version 2007-5-10
 * @author xalinx at gmail dot com
 * 
 */
public class SimpleDaoTemplate extends SimpleJdbcTemplate {

	private SqlBuilder sqlBuilder;

	public void setSqlBuilder(SqlBuilder sqlBuilder) {
		this.sqlBuilder = sqlBuilder;
	}

	/**
	 * @param classicJdbcTemplate
	 */
	public SimpleDaoTemplate(JdbcOperations classicJdbcTemplate) {
		super(classicJdbcTemplate);
	}

	@SuppressWarnings("unchecked")
	@Override
	public <T> T queryForObject(String sql, ParameterizedRowMapper<T> rm, Object... args) throws DataAccessException {
		Object obj = (ObjectUtils.isEmpty(args) ? getJdbcOperations().queryForObject(sql, rm) : getJdbcOperations()
				.queryForObject(sql, args, rm));
		return obj == null ? null : (T) obj;
	}

	public <T> T queryObject(String sql, ParameterizedRowMapper<? extends T> rm, Object... args) {
		return queryForObject(sql, rm, args);
	}

	@SuppressWarnings("unchecked")
	public <T> List<T> queryForList(String sql, ParameterizedRowMapper<? extends T> rm, Object... args)
			throws DataAccessException {
		return (List<T>) (ObjectUtils.isEmpty(args) ? getJdbcOperations().query(sql, rm) : getJdbcOperations().query(
				sql, args, rm));
	}

	public <T> BasePage<T> proxyQueryPage(BeanMonitor<T> beanMonitor, ParameterizedRowMapper<? extends T> rowMapper,
			PageQuery pageQuery) {
		QueryWrap wrap = sqlBuilder.buildLimitSelect(beanMonitor, pageQuery.getStart(), pageQuery.getPageSize());
		List<T> items = queryForList(wrap.getSql(), rowMapper, wrap.getValues());
		return new BasePage<T>(pageQuery, items);
	}

	public <T> List<T> proxyQueryList(BeanMonitor<T> monitor, ParameterizedRowMapper<? extends T> rm) {
		QueryWrap wrap = sqlBuilder.buildSelect(monitor);
		return queryForList(wrap.getSql(), rm, wrap.getValues());
	}

	public <T> T proxyQueryObject(BeanMonitor<T> monitor, ParameterizedRowMapper<? extends T> rm) {
		QueryWrap wrap = sqlBuilder.buildSelect(monitor);
		return queryObject(wrap.getSql(), rm, wrap.getValues());
	}

	public <T> void proxyStore(BeanMonitor<T> monitor) {
		QueryWrap wrap = sqlBuilder.buildInsert(monitor);
		update(wrap.getSql(), wrap.getValues());
	}

	public <T> void proxyDelete(BeanMonitor<T> monitor) {
		QueryWrap wrap = sqlBuilder.buildDelete(monitor);
		update(wrap.getSql(), wrap.getValues());
	}

	public <E> void proxyUpdate(BeanMonitor<E> monitor, Object id) {
		QueryWrap wrap = sqlBuilder.buildUpdate(monitor);
		update(wrap.getSql(), wrap.getValues());
	}

	public <E> int findCount(BeanMonitor<E> monitor) {
		if (null == monitor) {
			throw new IllegalArgumentException();
		}
		QueryWrap wrap = sqlBuilder.buildCount(monitor);
		return queryForInt(wrap.getSql(), wrap.getValues());
	}

	public <E> int findCount(Class<E> entity) {
		if (null == entity) {
			throw new IllegalArgumentException();
		}
		QueryWrap wrap = sqlBuilder.buildCount(entity);
		return queryForInt(wrap.getSql(), wrap.getValues());
	}
}
